package main

import (
	"api/core"
	"api/dao/mysql/db"
	"api/global"
	"api/router"
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

// @title email console
// @version 1.0
// @Security ApiKeyAuth
func main() {
	// init configure file
	dir, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
		return
	}
	global.BasePath = strings.Replace(dir, "\\", "/", -1)
	err = core.Setting(&global.AppConfig, global.BasePath+"/config/config.yaml")
	if err != nil {
		log.Fatal(err)
		return
	}

	// init logger
	logInit := core.Logger{
		Level:      global.AppConfig.Zap.Level,
		Directory:  global.AppConfig.Zap.Directory,
		Format:     global.AppConfig.Zap.Format,
		MaxSize:    global.AppConfig.Zap.MaxSize,
		MaxAge:     global.AppConfig.Zap.MaxAge,
		MaxBackups: global.AppConfig.Zap.MaxBackups,
		Compress:   global.AppConfig.Zap.Compress,
	}
	global.Logger = logInit.NewLogger()

	// init db
	db := db.MySQLDB{
		Config: global.AppConfig.MySQL,
	}
	err = db.NewDb()

	if err != nil {
		global.Logger.Error(fmt.Sprintf("%v", err))
		return
	}
	defer db.Close()
	db.Db.Exec("use " + global.AppConfig.MySQL.DbName)
	global.DBHandle = db.Db

	r := router.SetupRouter(&global.AppConfig)

	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", global.AppConfig.Port),
		Handler: r,
	}

	go func() {
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()

	quit := make(chan os.Signal, 1) // create a receive signal channel
	// kill default send a syscall.SIGTERM signal
	// kill -2 send a syscall.SIGINT signal, Ctrl+C trigger SIGINT signal
	// kill -9 send a syscall.SIGKILL signal, But it can't be captured, so you don't need to add it
	// signal.Notify Send the received syscall.SIGINT or syscall.SIGTERM forwarded to quit channel
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // No blocking here
	<-quit                                               // Blocking here, the execution will be carried out only when the above two signals(syscall.SIGTERM and syscall.SIGINT) are received
	log.Println("Shutdown Server ...")
	// Create a 5-second timeout context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	// Turn off the service within 5 seconds (turn off the service after processing the unprocessed requests), and exit after 5 seconds
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown: ", err)
	}

	log.Println("Server exiting")

}
